package com.yilin.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yilin.platform.base_core.commons.exception.BusinessException;
import com.yilin.platform.base_core.commons.utils.ArrayUtil;
import com.yilin.platform.base_core.commons.utils.DateTimeUtil;
import com.yilin.platform.base_core.tools.cmbc.entity.balanceDetails.DataStream;
import com.yilin.platform.base_core.tools.cmbc.entity.balanceDetails.TrsDtlDownLoad;
import com.yilin.platform.base_core.commons.utils.MapUtil;
import com.yilin.platform.base_core.commons.utils.ParamUtil;
import com.yilin.platform.entity.cmbc.CmbcTradeRecord;
import com.yilin.platform.entity.capital.TradeFlow;
import com.yilin.platform.entity.user.AccountConfigure;
import com.yilin.platform.mapper.cmbc.CmbcTradeRecordMapper;
import com.yilin.platform.service.IBankCmbcService;
import com.yilin.platform.base_core.tools.cmbc.utils.CmbcResData;
import com.yilin.platform.base_core.tools.cmbc.utils.XmlBodyTools;
import com.yilin.platform.base_core.tools.cmbc.utils.XmlBuilder;
import com.yilin.platform.service.ITradeFlowService;
import com.yilin.platform.service.IUserService;
import org.apache.commons.codec.binary.Base64;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/***
 * 民生银行 · 银企直连
 * 客户调联接口
 * BY: 杨海平
 * */
@Service
public class BankCmbcService extends ServiceImpl<CmbcTradeRecordMapper, CmbcTradeRecord> implements IBankCmbcService {
    private Logger logger = LoggerFactory.getLogger(BankCmbcService.class);

    @Value("${cmbc-bank-enterprise.req-url}")
    private String cmbcReqUrl;

    @Resource
    CmbcTradeRecordMapper cmbcTradeRecordMapper;
    @Resource
    BankCmbcService bankCmbcService;
    @Resource
    IUserService userService;
    @Resource
    ITradeFlowService tradeFlowService;


    /*单笔转账 */
    @Override
    public CmbcResData transferXfer(CmbcTradeRecord recordFlow) {
        CmbcResData cmbcResData = XmlBodyTools.Xfer(recordFlow.getTradeNo(), recordFlow.getOutAcctNo(), recordFlow.getOutAcctName(), recordFlow.getInAcctNo(),
                recordFlow.getInAcctName(), recordFlow.getExternBank(), recordFlow.getLocalFlag(), recordFlow.getRcvCustType(),
                recordFlow.getBankCode(), recordFlow.getBankName(), recordFlow.getBankAddr(), recordFlow.getAreaCode(), recordFlow.getTranAmount().toString(),
                recordFlow.getExplain(), recordFlow.getCertNo());
        recordFlow.setInitiateTime(new Date());
        HashMap<String, Object> transfer = (HashMap<String, Object>) cmbcResData.getDataMap().get("transfer");
        recordFlow.setBankFlowNo(MapUtil.getMapString(transfer, "svrId"));
        recordFlow.setStatus(CmbcTradeRecord.Status.handle);
        saveOrUpdate(recordFlow);
        return cmbcResData;
    }

    @Override
    public CmbcResData transferQryXfer(String insId, @Nullable String servid) {
        CmbcResData cmbcResData = XmlBodyTools.qryXfer(insId, servid);
        CmbcTradeRecord recordFlow = getRecordFlowByTradeNo(insId);
        try {
            updateRecordFlowStatus(recordFlow, cmbcResData.getDataMap());
        } finally {
            return cmbcResData;
        }
    }

    @Override
    public CmbcTradeRecord platTransferQryXfer(CmbcTradeRecord recordFlow) {
        CmbcResData cmbcResData = XmlBodyTools.qryXfer(recordFlow.getTradeNo(), null);
        return updateRecordFlowStatus(recordFlow, cmbcResData.getDataMap());
    }


    /*批量转账*/
    @Override
    public CmbcResData transferBatchXfer(String batchNo, String payerAcct, List<Map<String, Object>> mapList) {
        List<CmbcTradeRecord> recordFlowList = getRecordFlowByBatchNo(batchNo);
        ParamUtil.isNull(recordFlowList, "获取支付信息失败");
        CmbcResData cmbcResData = XmlBodyTools.batchXfer(batchNo, payerAcct, mapList);
        for (CmbcTradeRecord recordFlow : recordFlowList) {
            recordFlow.setInitiateTime(new Date());
            recordFlow.setStatus(CmbcTradeRecord.Status.handle);
        }
        saveOrUpdateBatch(recordFlowList);
        return cmbcResData;
    }

    /* 批量费用报销、代发工资查*/
    @Override
    public CmbcResData batchCostReimbNew(String batchNo, String payerAcct, String payType, List<Map<String, Object>> mapList) {
        List<CmbcTradeRecord> recordFlowList = getRecordFlowByBatchNo(batchNo);
        ParamUtil.isNull(recordFlowList, "获取支付信息失败");
        CmbcResData cmbcResData = XmlBodyTools.batchCostReimbNew(batchNo, payerAcct, payType, mapList);
        for (CmbcTradeRecord recordFlow : recordFlowList) {
            recordFlow.setInitiateTime(new Date());
            recordFlow.setStatus(CmbcTradeRecord.Status.handle);
        }
        saveOrUpdateBatch(recordFlowList);
        return cmbcResData;
    }

    //    批量查询转账
    @Override
    public CmbcResData transferQryBatchXfer(String batchTradeNo) {
        List<CmbcTradeRecord> recordFlowList = getRecordFlowByBatchNo(batchTradeNo);
        ParamUtil.isNull(recordFlowList, "获取支付信息失败");
        CmbcResData cmbcResData = XmlBodyTools.qryBatchXfer(batchTradeNo);
        try {
            processCmbcResData(cmbcResData, recordFlowList);
        } finally {
            return cmbcResData;
        }
    }


    //    平台内部批量查询转账
    @Override
    public List<CmbcTradeRecord> platTransferQryBatch(List<CmbcTradeRecord> recordFlowList) {
        ParamUtil.isNull(recordFlowList, "获取支付信息失败");
        CmbcResData cmbcResData = XmlBodyTools.qryBatchXfer(recordFlowList.get(0).getBatchNo());
        return processCmbcResData(cmbcResData, recordFlowList);
    }


    //    平台内部批量费用报销，代发工资
    @Override
    public List<CmbcTradeRecord> platTransferQryHealfBatch(List<CmbcTradeRecord> recordFlowList) {
        ParamUtil.isNull(recordFlowList, "获取支付信息失败");
        CmbcResData cmbcResData = XmlBodyTools.qryBatchCostReimbNew(recordFlowList.get(0).getBatchNo());
        return processCmbcResDatahCostReimb(cmbcResData, recordFlowList);
    }


////TODO   ==============================================余额明细模块=================================================================


    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能：定期账户明细查询交易(depositAccountDetail)
     * 备注:
     *
     * @param companyNo 单号账号
     * @param beginDate 开始日期
     * @param endDate   截止日期
     */
    @Override
    public CmbcResData depositAccountDetail(String companyNo, Date beginDate, Date endDate) {
        CmbcResData cmbcResData = XmlBodyTools.depositAccountDetail(companyNo, beginDate, endDate);
        return cmbcResData;
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能：银企直联明细下载(新)(trsDtlDownLoad)
     * 备注:
     *
     * @param acntNo    单号账号
     * @param dateFrom  开始日期
     * @param dateTo    截止日期
     * @param sartNo    开始页
     * @param queryRows 显示多少条
     */
    @Override
    public TrsDtlDownLoad trsDtlDownLoad(String acntNo, Date dateFrom, Date dateTo, Integer
            sartNo, Integer queryRows) {
        CmbcResData cmbcResData = XmlBodyTools.trsDtlDownLoad(acntNo, dateFrom, dateTo, sartNo, queryRows);
        TrsDtlDownLoad trsDtlDownLoad = XmlBuilder.convertXMLToObject(cmbcResData, TrsDtlDownLoad.class);
        Map<String, Object> dataMap = cmbcResData.getDataMap();
        trsDtlDownLoad.setTotalNum(MapUtil.getMapString(dataMap, "totalNum"));
        String listStr = MapUtil.getMapString(dataMap, "dataStream");
        String[] fileContentStrArrs = listStr.split("0x0A");
        List<DataStream> dataStreamList = new ArrayList<>();
        for (String dataStreamStr : fileContentStrArrs) {
            String[] content = dataStreamStr.split("\\|");
            DataStream dataStream = new DataStream();
            dataStream.setTradeDate(content[0]);
            dataStream.setTradeFlowNo(content[1]);
            dataStream.setAccountingFlowNo(content[2]);
            dataStream.setInsId(content[3]);
            dataStream.setTradeNo(content[4]);
            dataStream.setBorrowerAmt(content[5]);
            dataStream.setLenderAmt(content[6]);
            dataStream.setBalance(content[7]);
            dataStream.setVoucherType(content[8]);
            dataStream.setVoucherNo(content[9]);
            dataStream.setUseTo(content[10]);
            dataStream.setRemark(content[11]);
            dataStream.setTradeAddress(content[12]);
            dataStream.setSideAccNo(content[13]);
            dataStream.setSideAccName(content[14]);
            dataStream.setSideOpenName(content[15]);
            dataStream.setTradeTime(content[16]);
            dataStreamList.add(dataStream);
        }
        trsDtlDownLoad.setDataStreamList(dataStreamList);
        return trsDtlDownLoad;
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能：余额查询交易（新）(qryBalNew)
     * 备注:
     *
     * @param acntNos 成员单位账号
     */
    @Override
    public CmbcResData qryBalNew(String[] acntNos) {
        return XmlBodyTools.qryBalNew(acntNos);
    }


    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能：历史余额查询(qryHistoryBal)
     * 备注:
     *
     * @param acntNo  查询账号（★） 32
     * @param qryDate 查询时间(若不输入，则默认查询当日余额)(格
     */
    @Override
    public CmbcResData qryHistoryBal(String acntNo, @Nullable Date qryDate) {
        return XmlBodyTools.qryHistoryBal(acntNo, qryDate);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能：交易明细查询(qryTrsDtl)
     * 备注:
     *
     * @param acntNo   待查明细的单位账号（★）
     * @param dateFrom 开始日期（含）格式为YYYY-MM-DD（★） 10
     * @param dateTo   截止日期（含）格式为YYYY-MM-DD（★）
     * @param startNo  开始条数，必须是有意义的数字
     * @param endNo    结束条数，必须是有意义的数字
     */
    @Override
    public CmbcResData qryTrsDtl(String acntNo, Date dateFrom, Date dateTo, Integer startNo, Integer endNo) {
        return XmlBodyTools.qryTrsDtl(acntNo, dateFrom, dateTo, startNo, endNo);
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能：交易明细对账单PDF下载(ElectNotePrint)
     * 备注:
     *
     * @param acntNo    待查明细的单位账号（★）
     * @param startDate 开始日期（含）为YYYYMMDD（★）
     * @param endDate   截止日期（含）为YYYYMMDD（★）
     *                  返回FileContent返回文件体 FileName 文件名称
     */
    @Override
    public CmbcResData electNotePrint(String acntNo, Date startDate, Date endDate) {
        CmbcResData cmbcResData = XmlBodyTools.electNotePrint(acntNo, startDate, endDate);
        try {
            byte[] decodedBytes = Base64.decodeBase64(MapUtil.getMapString(cmbcResData.getDataMap(), "FileContent"));
            String base64String = Base64.encodeBase64String(decodedBytes);
            cmbcResData.getDataMap().put("FileContent", "data:application/pdf;" + base64String);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cmbcResData;
    }


    ////TODO   ==============================================网上对账=================================================================
//
//        /**
//         * 创建人：yhp 时间：2023年7月6日09:40:48   功能：网上对账开通信息维护(DebtMaintainB2e)
//         * 备注:
//         *
//         * @param platId      平台ID
//         * @param tradeNo     一条转账指令在客户端的唯一标识
//         * @param contactName 联系人名称（★）
//         * @param companyTel  公司电话（★）
//         * @param phone       联系人手机
//         * @param operateType 操作类型（★）0：开通，1：修改，2：关闭
//         *                    返回，trnId 客户端交易的 唯一标志  svrId 交易流水号  insId 指令ID，
//         */
//        @Override
//        public Map<String, Object> debtMaintainB2e (String platId, String tradeNo, String contactName, String
//        companyTel, String phone, Integer operateType){
//            HatchCmbc hatchCmbc = ParamUtil.isSuccess(userRemote.getCmbcHatch(platId));
//            ParamUtil.isNull(hatchCmbc, "获取民生银行配置失败");
//            XmlReturnMap xmlReturnMap = XmlBodyTools.debtMaintainB2e(tradeNo, contactName, companyTel, phone, operateType);
//            CmbcResData cmbcResData = XmlBodyTools.postCmbcItemDataJ(hatchCmbc, xmlReturnMap);
//            return cmbcResData.getDataMap();
//        }
//
//        /**
//         * 创建人：yhp 时间：2023年7月6日09:40:48   功能：明细对账单查询(QryDebtDetialList)
//         * 备注:
//         *
//         * @param platId       平台ID
//         * @param acNo         一银行账号
//         * @param qryStartDate 开始日期
//         * @param qryEndDate   截止日期
//         * @param currentIndex 起始笔数
//         * @param pageSize     查询笔数
//         * @param customNo     此字段为空查询本公司明细对账* 信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
//         */
//        @Override
//        public QryDebtDetialList qryDebtDetialList (String platId, String acNo, Date qryStartDate, Date
//        qryEndDate, Integer currentIndex, Integer pageSize, @Nullable String customNo){
//            HatchCmbc hatchCmbc = ParamUtil.isSuccess(userRemote.getCmbcHatch(platId));
//            ParamUtil.isNull(hatchCmbc, "获取民生银行配置失败");
//            XmlReturnMap xmlReturnMap = XmlBodyTools.qryDebtDetialList(acNo, qryStartDate, qryEndDate, currentIndex, pageSize, customNo);
//            CmbcResData cmbcResData = XmlBodyTools.postCmbcItemDataJ(hatchCmbc, xmlReturnMap);
//            return XmlBuilder.convertXMLToObject(cmbcResData, QryDebtDetialList.class);
//        }
//
//        /**
//         * 创建人：yhp 时间：2023年7月6日09:40:48   功能： 已填写调节表查询(QryDebtReChkDetail)
//         * 备注:
//         *
//         * @param platId    平台ID
//         * @param customNo  成员客户 如果不为空,则查询所填写
//         * @param acNo      银行账号
//         * @param checkDate 对账日期
//         * @param customNo  此字段为空查询本公司明细对账* 信息;如果不为空,则查询所填写的成员公司明细对账信息;(成员公司与本公司必须有签约关系)
//         */
//        @Override
//        public QryDebtReChkDetail qryDebtReChkDetail (String platId, @Nullable String customNo, String acNo, Date
//        checkDate){
//            HatchCmbc hatchCmbc = ParamUtil.isSuccess(userRemote.getCmbcHatch(platId));
//            ParamUtil.isNull(hatchCmbc, "获取民生银行配置失败");
//            XmlReturnMap xmlReturnMap = XmlBodyTools.qryDebtReChkDetail(customNo, acNo, checkDate);
//            CmbcResData cmbcResData = XmlBodyTools.postCmbcItemDataJ(hatchCmbc, xmlReturnMap);
//            return XmlBuilder.convertXMLToObject(cmbcResData, QryDebtReChkDetail.class);
//        }
//
//        /**
//         * 创建人：yhp 时间：2023年7月6日09:40:48   功能： 对账结果查询(QryDebtResultList)
//         * 备注:
//         *
//         * @param platId       平台ID
//         * @param acNo         银行账号
//         * @param customNo     成员客户号（★）
//         * @param qryType      查询类型 (
//         * @param qryStartDate 开始日期（★）
//         * @param qryEndDate   截止日期（★）
//         * @param currentIndex 起始笔数（★）
//         * @param pageSize     查询笔数（★）
//         */
//        @Override
//        public QryDebtResultList qryDebtResultList (String platId, String acNo, String customNo, Integer qryType, Date
//        qryStartDate, Date qryEndDate, Integer currentIndex, Integer pageSize){
//            HatchCmbc hatchCmbc = ParamUtil.isSuccess(userRemote.getCmbcHatch(platId));
//            ParamUtil.isNull(hatchCmbc, "获取民生银行配置失败");
//            XmlReturnMap xmlReturnMap = XmlBodyTools.qryDebtResultList(acNo, customNo, qryType, qryStartDate, qryEndDate, currentIndex, pageSize);
//            CmbcResData cmbcResData = XmlBodyTools.postCmbcItemDataJ(hatchCmbc, xmlReturnMap);
//            return XmlBuilder.convertXMLToObject(cmbcResData, QryDebtResultList.class);
//        }
//
//        /**
//         * 创建人：yhp 时间：2023年7月6日09:40:48   功能： 可填写对账单回执列表(QryVerifyAccRecList)
//         * 备注:
//         *
//         * @param platId    平台ID
//         * @param startNo   起始笔数（★）
//         * @param queryRows 查询笔数（★）
//         * @param customNo  成员客户号（★）
//         * @param qryDate   查询时间（★）
//         */
//        @Override
//        public QryVerifyAccRecList qryVerifyAccRecList (String platId, Integer startNo, Integer queryRows, String
//        customNo, Date qryDate){
//            HatchCmbc hatchCmbc = ParamUtil.isSuccess(userRemote.getCmbcHatch(platId));
//            ParamUtil.isNull(hatchCmbc, "获取民生银行配置失败");
//            XmlReturnMap xmlReturnMap = XmlBodyTools.qryVerifyAccRecList(startNo, queryRows, customNo, qryDate);
//            CmbcResData cmbcResData = XmlBodyTools.postCmbcItemDataJ(hatchCmbc, xmlReturnMap);
//            return XmlBuilder.convertXMLToObject(cmbcResData, QryVerifyAccRecList.class);
//        }
//
//        /**
//         * 创建人：yhp 时间：2023年7月6日09:40:48   功能：  对账日期查询(QryVerifyAccRecordDate)
//         * 备注:
//         *
//         * @param platId   平台ID
//         * @param customNo 成员客户号
//         * @param qryDate  查询时间
//         *                 返回 beQryYear 查询年份（★） List  beQryMonth 可查月份（★）
//         */
//        @Override
//        public Map<String, Object> qryVerifyAccRecordDate (String platId, String customNo, Date qryDate){
//            HatchCmbc hatchCmbc = ParamUtil.isSuccess(userRemote.getCmbcHatch(platId));
//            ParamUtil.isNull(hatchCmbc, "获取民生银行配置失败");
//            XmlReturnMap xmlReturnMap = XmlBodyTools.qryVerifyAccRecordDate(customNo, qryDate);
//            CmbcResData cmbcResData = XmlBodyTools.postCmbcItemDataJ(hatchCmbc, xmlReturnMap);
//            return cmbcResData.getDataMap();
//        }
//
//        /**
//         * 创建人：yhp 时间：2023年7月6日09:40:48   功能：   对账单回执确认(VerifyAccRecConf)
//         * 备注:
//         *
//         * @param platId   平台ID
//         * @param customNo 成员客户号
//         * @param qryDate  查询时间
//         *                 返回 beQryYear 查询年份（★） List  beQryMonth 可查月份（★）
//         */
//        @Override
//        public Map<String, Object> verifyAccRecConf (String platId, String customNo, Date qryDate){
////
//            return null;
//        }
//TODO   ==============================================账户查询=================================================================

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能：  活期存款列表查询交易(qryAcctList)
     * 备注:
     */
    @Override
    public CmbcResData qryAcctList() {
        return XmlBodyTools.qryAcctList();
    }

//        //TODO   ==============================================回单=================================================================

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：客户账单回单下载（支持最多3个同时下载）(b2eElectNoteDownLoadNew)
     * 备注
     *
     * @param acNo      账号（★）
     * @param innerNos  回单编号（★）
     * @param fileNames 文件名称（★）
     * @param operFlag  操作标识下载（★）
     * @param needSign  是否添加可信签章
     */
    @Override
    public CmbcResData b2eElectNoteDownLoadNew(String acNo, String[] innerNos, String[] fileNames, Integer operFlag, @Nullable Integer needSign) {
        CmbcResData cmbcResData = XmlBodyTools.b2eElectNoteDownLoadNew(acNo, innerNos, fileNames, operFlag, needSign);
        try {
            byte[] decodedBytes = Base64.decodeBase64(MapUtil.getMapString(cmbcResData.getDataMap(), "FileContent"));
            // 写入文件
            String base64String = Base64.encodeBase64String(decodedBytes);
            cmbcResData.getDataMap().put("FileContent", base64String);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cmbcResData;
    }

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48 功能：客户回单查询(ElectnoteListQry) (支持T0，T-n日回单)
     * 备注
     *
     * @param saAcctNo     账号（★）
     * @param qryStartDate 查询起始日期（★）
     * @param qryEndDate   查询截止日期（★）
     * @param printState   打印状态0
     * @param minMoney     发生额范围小
     * @param maxMoney     发生额范围大
     * @param loanFlag     借贷标识
     * @param pageNo       当前页码
     * @param pageSize     查询笔数
     */
    @Override
    public CmbcResData electnoteListQry(String saAcctNo, Date qryStartDate, Date qryEndDate, Integer printState,
                                        Double minMoney, Double maxMoney, Integer loanFlag, Integer pageNo, Integer pageSize) {

        return XmlBodyTools.electnoteListQry(saAcctNo, qryStartDate, qryEndDate, printState, minMoney, maxMoney, loanFlag, pageNo, pageSize);
    }
    //TODO   ==============================================利率查询=================================================================

    /**
     * 创建人：yhp 时间：2023年7月6日09:40:48   功能： 利率查询(InterestSettlementQryB2e)
     * 备注:
     *
     * @param insId   交易流水号（★）
     * @param acNo    银行账号（★）
     * @param qryDate 查询日期（★）
     */
    @Override
    public CmbcResData interestSettlementQryB2e(String insId, String acNo, Date qryDate) {
        return XmlBodyTools.interestSettlementQryB2e(insId, acNo, qryDate);
    }
//TODO   ==============================================利率查询=================================================================


    /*根据银行名称获取银行信息*/
    @Override
    public List<Map<String, Object>> getBankBatchBankNo(String[] bankName) {
        CmbcResData cmbcResData = XmlBodyTools.b2eBatchBankNo(Arrays.asList(bankName));
        String svrId = MapUtil.getMapString(cmbcResData.getDataMap(), "svrId");

        if (svrId == null) {
            return null;
        }

        try {
            CmbcResData cmbcResDataNew = XmlBodyTools.b2eQryBatchBankNo(svrId);
            Map<String, Object> matchResultList = (Map<String, Object>) cmbcResDataNew.getDataMap().get("matchResultList");
            if (matchResultList != null && matchResultList.get("item") instanceof List) {
                return (List<Map<String, Object>>) matchResultList.get("item");
            }
        } catch (Exception e) {
            throw new BusinessException("查询银行联行号和开户行名称，数据类型转换错误");
        }
        return null;
    }

    /*银行公告查询*/
    @Override
    public CmbcResData getEntNoticeQryB2e() {
        return XmlBodyTools.entNoticeQryB2e();
    }

    @Override
    public Map<String, Object> getCmbcInfo() {
        Map<String, Object> map = new HashMap<>();
        map.put("reqUrl", cmbcReqUrl);
        return map;
    }

    //###################################################内部方法####################################################################
    private CmbcTradeRecord updateRecordFlowStatus(CmbcTradeRecord recordFlow, Map<String, Object> dataMap) {
        if (recordFlow != null && dataMap != null) {
            Map<String, Object> statusIdMap = (Map<String, Object>) dataMap.get("statusId");
            String statusCode = MapUtil.getMapString(statusIdMap, "statusCode");
            if (statusCode.equals("0") || statusCode.equals("5")) {
                recordFlow.setStatus(CmbcTradeRecord.Status.success);
                if (recordFlow.getCompleteTime() == null) recordFlow.setCompleteTime(new Date());
                tradeRecordBySaveTradeFlow(Collections.singletonList(recordFlow));
            } else if (statusCode.equals("2")) {
                recordFlow.setStatus(CmbcTradeRecord.Status.fail);
            } else if (statusCode.equals("3") || statusCode.equals("4")) {
                recordFlow.setStatus(CmbcTradeRecord.Status.handle);
            }

        }
        saveOrUpdate(recordFlow);
        return recordFlow;
    }

    private List<CmbcTradeRecord> processCmbcResData(CmbcResData cmbcResData, List<CmbcTradeRecord> recordFlowList) {
        List<CmbcTradeRecord> recordFlowListNew = new ArrayList<>();
        if (cmbcResData.getDataMap() != null) {
            Map<String, Object> batchtransfersMap = (Map<String, Object>) cmbcResData.getDataMap().get("batchTransfers");
            String fileContentStr = String.valueOf(batchtransfersMap.get("fileContent"));
            String bankFlowNo = (String) batchtransfersMap.get("insId");
            String[] fileContentStrArrs = fileContentStr.split("\\^");
            for (String fileContent : fileContentStrArrs) {
                String[] content = fileContent.split("\\|");
                String certNo = content[0];//企业自制凭证号
                String paymentAccNo = content[1];//付款人账号32
                String paymentName = content[2];//付款人名称
                String paymentBankName = content[3];//付款人行名4
                String incomeAccNo = content[4];//收款人账号3
                String incomeName = content[5];//收款人名称
                String incomeBankName = content[6];//收款行行名
                String amount = content[7];//金额1
                String status = content[8];//交易状态：1:成功;2:失败
                String erroMsg = content[9];//错误信
                CmbcTradeRecord recordFlow = recordFlowList.stream().filter(tradeRecordNew -> tradeRecordNew.getInAcctNo().equals(incomeAccNo)).findFirst().orElse(null);
                if (recordFlow == null) continue;
                if (status.equals("1")) {
                    recordFlow.setStatus(CmbcTradeRecord.Status.success);
                    recordFlow.setBankFlowNo(bankFlowNo);
                    if (recordFlow.getCompleteTime() == null) recordFlow.setCompleteTime(new Date());
                } else if (status.equals("2")) {
                    recordFlow.setStatus(CmbcTradeRecord.Status.fail);
                } else {
                    continue;
                }
                recordFlowListNew.add(recordFlow);
            }
            tradeRecordBySaveTradeFlow(recordFlowListNew);
            saveOrUpdateBatch(recordFlowListNew);
        }
        return recordFlowListNew;
    }


    private List<CmbcTradeRecord> processCmbcResDatahCostReimb(CmbcResData cmbcResData, List<CmbcTradeRecord> recordFlowList) {
        List<CmbcTradeRecord> recordFlowListNew = new ArrayList<>();
        if (cmbcResData.getDataMap() != null) {
            Map<String, Object> batchtransfersMap = (Map<String, Object>) cmbcResData.getDataMap().get("batchTransfers");
            String fileContentStr = String.valueOf(batchtransfersMap.get("fileContent"));
            String bankFlowNo = (String) batchtransfersMap.get("insId");
            String[] fileContentStrArrs = fileContentStr.split("\\^");
            for (String fileContent : fileContentStrArrs) {
                String[] content = fileContent.split("\\|");
                String certNo = content[0];//企业自制凭证号
                String paymentAccNo = content[1];//付款人账号32
                String paymentName = content[2];//付款人名称
                String paymentBankName = content[3];//付款人行名4
                String incomeAccNo = content[4];//收款人账号3
                String incomeName = content[5];//收款人名称
                String incomeBankName = content[6];//收款行行名
                String amount = content[7];//金额1
                String userTo = content[8];//用途
                String remark = content[9];//备注
                String remark1 = content[10];//备用字段1
                String remark2 = content[11];//备用字段1
                String remark3 = content[12];//备用字段1
                String tradeNo = content[13];//交易参考号6
                String status = content[14];//交易状态：10:成功;20:失败
                String erroMsg = content[15];//错误信
                CmbcTradeRecord recordFlow = recordFlowList.stream().filter(tradeRecordNew -> tradeRecordNew.getInAcctNo().equals(incomeAccNo)).findFirst().orElse(null);
                if (recordFlow == null) continue;
                if (status.equals("10")) {
                    recordFlow.setStatus(CmbcTradeRecord.Status.success);
                    recordFlow.setBankFlowNo(bankFlowNo);
                    if (recordFlow.getCompleteTime() == null) recordFlow.setCompleteTime(new Date());
                } else if (status.equals("20")) {
                    recordFlow.setStatus(CmbcTradeRecord.Status.fail);
                } else {
                    continue;
                }
                recordFlowListNew.add(recordFlow);
            }
            tradeRecordBySaveTradeFlow(recordFlowListNew);
            saveOrUpdateBatch(recordFlowListNew);
        }
        return recordFlowListNew;
    }

//########################################静态方法##############################################################

    private void tradeRecordBySaveTradeFlow(List<CmbcTradeRecord> cmbcTradeRecordList) {
        List<TradeFlow> tradeFlows = new ArrayList<>();
        for (CmbcTradeRecord tradeRecord : cmbcTradeRecordList) {
            if (tradeRecord.getStatus() != CmbcTradeRecord.Status.success) return;
            TradeFlow[] flows = tradeFlowService.generateTradeFlows(tradeRecord.getTradeName(), TradeFlow.PayType.cmbcPay, tradeRecord);
            tradeFlows.addAll(ArrayUtil.initList(flows));
        }
        if (tradeFlows.size() == 0) return;
        tradeFlowService.saveOrUpdateBatch(tradeFlows);
    }

    // ---本地---

    @Override
    public List<CmbcTradeRecord> getRecordFlowByBatchNo(String batchNo) {
        QueryWrapper<CmbcTradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("batch_no", batchNo);
        queryWrapper.eq("is_deleted", 0);
        return cmbcTradeRecordMapper.selectList(queryWrapper);
    }

    @Override
    public CmbcTradeRecord getRecordFlowByTradeNo(String tradeNo) {
        QueryWrapper<CmbcTradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("trade_no", tradeNo);
        queryWrapper.eq("is_deleted", 0);
        return cmbcTradeRecordMapper.selectOne(queryWrapper);
    }

    //   获取单笔转账需要查询的
    @Override
    public List<CmbcTradeRecord> getNotificationList() {
        QueryWrapper<CmbcTradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.nested(i ->
                i.or(j -> j.eq("status", 1).le("next_wait_time", new Date()))
                        .or(j -> j.eq("status", 2).eq("notified_yilin", 0))
                        .or(j -> j.eq("status", 3).eq("notified_yilin", 0))
                        .or(j -> j.eq("status", 4).eq("notified_yilin", 0)))
                .eq("pay_type", CmbcTradeRecord.PayType.transfer)
                .eq("is_deleted", 0)
                .le("next_notification_time", new Date());
        return cmbcTradeRecordMapper.selectList(queryWrapper);
    }

    //   获转批量转账需要查询的
    @Override
    public List<CmbcTradeRecord> getNotificationBatchNoList() {
        QueryWrapper<CmbcTradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.nested(i ->
                i.or(j -> j.eq("status", 1).le("next_wait_time", new Date()))
                        .or(j -> j.eq("status", 2).eq("notified_yilin", 0))
                        .or(j -> j.eq("status", 3).eq("notified_yilin", 0))
                        .or(j -> j.eq("status", 4).eq("notified_yilin", 0)))
                .eq("pay_type", CmbcTradeRecord.PayType.batchTransfer)
                .eq("is_deleted", 0)
                .le("next_notification_time", new Date()); // /下次通知时间小于当前时间
        return cmbcTradeRecordMapper.selectList(queryWrapper);
    }

    //   获转批量代发工资费用报销需要查询的
    @Override
    public List<CmbcTradeRecord> getNotificationBatchBehalfNoList() {
        QueryWrapper<CmbcTradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.nested(i ->
                i.or(j -> j.eq("status", 1).le("next_wait_time", new Date()))
                        .or(j -> j.eq("status", 2).eq("notified_yilin", 0))
                        .or(j -> j.eq("status", 3).eq("notified_yilin", 0))
                        .or(j -> j.eq("status", 4).eq("notified_yilin", 0)))
                .eq("pay_type", CmbcTradeRecord.PayType.batchBehalf)
                .eq("is_deleted", 0)
                .le("next_notification_time", new Date()); // /下次通知时间小于当前时间
        return cmbcTradeRecordMapper.selectList(queryWrapper);
    }

    //    定时函数单笔查询
    @Override
    public void myTaskOneMinute() {
        List<CmbcTradeRecord> recordFlowList = getNotificationList();
        if (recordFlowList == null || recordFlowList.size() < 1) return;
        List<CmbcTradeRecord> recordSuccess = new ArrayList<>();
        List<CmbcTradeRecord> recordHandle = new ArrayList<>();
        for (CmbcTradeRecord recordFlow : recordFlowList) {
            try {
                if (recordFlow.getStatus() == CmbcTradeRecord.Status.handle)
                    recordFlow = bankCmbcService.platTransferQryXfer(recordFlow);
            } catch (Exception e) {
                logger.info("定时函数查询单笔转账异常：" + e.getMessage());
                continue;
            }
            if (recordFlow.getStatus() == CmbcTradeRecord.Status.success||recordFlow.getStatus() == CmbcTradeRecord.Status.fail) {
                recordSuccess.add(recordFlow);
            }else if (recordFlow.getStatus() == CmbcTradeRecord.Status.handle) {
                recordFlow.setNextWaitTime(DateTimeUtil.queryWaitByCount(new Date(), recordFlow.getQueryWaitCount()));
                recordFlow.setQueryWaitCount(recordFlow.getQueryWaitCount() + 1);
                recordHandle.add(recordFlow);
            }
        }
        if (recordHandle.size() > 0) saveOrUpdateBatch(recordHandle);
        if (recordSuccess.size() > 0) processNotificationStatus(recordSuccess);
    }

    /*定时函数调用批量查询接口*/
    @Override
    public void myTaskOneMinuteBatch() {
        List<CmbcTradeRecord> recordFlowList = getNotificationBatchNoList();
        if (recordFlowList == null || recordFlowList.size() < 1) return;
        List<CmbcTradeRecord> processedList = new ArrayList<>();
        List<CmbcTradeRecord> recordSuccess = new ArrayList<>();
        List<CmbcTradeRecord> recordHandle = new ArrayList<>();
        // 根据BatchNo进行分组
        Map<String, List<CmbcTradeRecord>> recordsByBatchNo = recordFlowList.stream().collect(Collectors.groupingBy(CmbcTradeRecord::getBatchNo));
        try {
            recordsByBatchNo.forEach((batchNo, records) -> processedList.addAll(bankCmbcService.platTransferQryBatch(records)));
        } catch (Exception e) {
            for (CmbcTradeRecord recordFlow : processedList) {
                recordFlow.setNextWaitTime(DateTimeUtil.queryBatchWaitByCount(new Date(), recordFlow.getQueryWaitCount()));
                recordFlow.setQueryWaitCount(recordFlow.getQueryWaitCount() + 1);
                recordHandle.add(recordFlow);
            }
            saveOrUpdateBatch(recordHandle);
            throw new BusinessException(e.getMessage());
        }
        for (CmbcTradeRecord recordFlow : processedList) {
            if (recordFlow.getStatus() == CmbcTradeRecord.Status.success||recordFlow.getStatus() == CmbcTradeRecord.Status.fail) {
                recordSuccess.add(recordFlow);
            }else if (recordFlow.getStatus() == CmbcTradeRecord.Status.handle) {
                recordFlow.setNextWaitTime(DateTimeUtil.queryBatchWaitByCount(new Date(), recordFlow.getQueryWaitCount()));
                recordFlow.setQueryWaitCount(recordFlow.getQueryWaitCount() + 1);
                recordHandle.add(recordFlow);
            }
        }
        if (recordHandle.size() > 0) saveOrUpdateBatch(recordHandle);
        if (recordSuccess.size() > 0) processNotificationStatus(recordSuccess);
    }

    /*定时函数代发工资费用报销*/
    @Override
    public void myTaskOneMinuteBehalfBatch() {
        List<CmbcTradeRecord> recordFlowList = getNotificationBatchBehalfNoList();
        if (recordFlowList == null || recordFlowList.size() < 1) return;
        List<CmbcTradeRecord> processedList = new ArrayList<>();
        List<CmbcTradeRecord> recordSuccess = new ArrayList<>();
        List<CmbcTradeRecord> recordHandle = new ArrayList<>();
        // 根据BatchNo进行分组
        Map<String, List<CmbcTradeRecord>> recordsByBatchNo = recordFlowList.stream().collect(Collectors.groupingBy(CmbcTradeRecord::getBatchNo));
        try {
            recordsByBatchNo.forEach((batchNo, records) -> processedList.addAll(bankCmbcService.platTransferQryHealfBatch(records)));
        } catch (Exception e) {
            for (CmbcTradeRecord recordFlow : processedList) {
                recordFlow.setNextWaitTime(DateTimeUtil.queryBatchWaitByCount(new Date(), recordFlow.getQueryWaitCount()));
                recordFlow.setQueryWaitCount(recordFlow.getQueryWaitCount() + 1);
                recordHandle.add(recordFlow);
            }
            saveOrUpdateBatch(recordHandle);
            throw new BusinessException(e.getMessage());
        }
        for (CmbcTradeRecord recordFlow : processedList) {
            if (recordFlow.getStatus() == CmbcTradeRecord.Status.success||recordFlow.getStatus() == CmbcTradeRecord.Status.fail) {
                recordSuccess.add(recordFlow);
            }
            else if (recordFlow.getStatus() == CmbcTradeRecord.Status.handle) {
                recordFlow.setNextWaitTime(DateTimeUtil.queryBatchWaitByCount(new Date(), recordFlow.getQueryWaitCount()));
                recordFlow.setQueryWaitCount(recordFlow.getQueryWaitCount() + 1);
                recordHandle.add(recordFlow);
            }
        }
        if (recordHandle.size() > 0) saveOrUpdateBatch(recordHandle);
        if (recordSuccess.size() > 0) processNotificationStatus(recordSuccess);
    }

    // 获取单笔转账处理中的条数
    @Override
    public Integer getCmbcHandleSingleTransferCount() {
        return cmbcTradeRecordMapper.getCmbcHandleSingleTransferCount();
    }

    // 获取批量转账处理中的条数
    @Override
    public Integer getCmbcHandleBatchTransferCount() {
        return cmbcTradeRecordMapper.getCmbcHandleBatchTransferCount();
    }

    //  获取批量费用报销，代发工资处理中的条数
    @Override
    public Integer getCmbcHandleFeeAgencyCount() {
        return cmbcTradeRecordMapper.getCmbcHandleFeeAgencyCount();
    }


    //##########################################内部方法####################################################################
    private void processNotificationStatus(List<CmbcTradeRecord> recordList) {
            List<Map<String,Object>> mapList=new ArrayList<>();
            for (int i = 0; i <recordList.size() ; i++) {
                String state=recordList.get(i).getStatus()== CmbcTradeRecord.Status.success?"paySuccess":"payFail";
                int finalI = i;
                mapList.add(MapUtil.generate(map1 -> {
                 map1.put("tradeNo",recordList.get(finalI).getTradeNo() );
                 map1.put("tradeStatus",state );
                 map1.put("bankFlowNo", recordList.get(finalI).getBankFlowNo() );
                 map1.put("finishTime", recordList.get(finalI).getCompleteTime() );
                 map1.put("tradeFailMsg", recordList.get(finalI).getBankMsg() );
             }));
              }
            Map<String, Object> paramMap = MapUtil.generate(map -> {
                map.put("tradeResults",new Gson().toJson(mapList));
                map.put("payType", "bankPay");
                map.put("bankType", "cmbcBankPay");
            });
            String status = null;
            try {
                status = userService.request("/capital/callback/bankPayResult", null, paramMap, new TypeToken<String>() {
                });
            } catch (Exception e) {
                for (CmbcTradeRecord recordFlow : recordList) {
                    recordFlow.setNextNotificationTime(DateTimeUtil.addTimeByCount(new Date(), recordFlow.getSyncTaskCount()));
                    recordFlow.setSyncTaskCount(recordFlow.getSyncTaskCount() + 1);
                }
                saveOrUpdateBatch(recordList);
                throw new BusinessException(e.getMessage());
            }
            if (status == null) return;
            for (CmbcTradeRecord recordFlow : recordList) {
                if (status.equals("SUCCESS")) {
                    recordFlow.setSyncTaskCount(0);
                    recordFlow.setNotifiedYilin(true);
                    recordFlow.setNotifyTime(new Date());
                } else {
                    recordFlow.setNextNotificationTime(DateTimeUtil.addTimeByCount(new Date(), recordFlow.getSyncTaskCount()));
                    recordFlow.setSyncTaskCount(recordFlow.getSyncTaskCount() + 1);
                }
            }
            saveOrUpdateBatch(recordList);
    }
}
